package zdm.servlet;

import zdm.annotation.ZdmController;
import zdm.annotation.ZdmRequestMapping;
import zdm.annotation.ZdmRequestParam;
import zdm.core.ApplicationContext;
import zdm.core.BeanFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: 张德明
 * @CreateTime: 2025-06-18 10:14:27
 * @Description: zdm.servlet
 */

@WebServlet(name = "dispatcher", urlPatterns = "/")
public class DispatcherServlet extends HttpServlet {

    // URL到HandlerMethod的映射表
    private Map<String, HandlerMethod> handlerMapping = new HashMap<>();

    // HandlerMethod内部类，封装控制器对象和方法
    private static class HandlerMethod {
        private Object controller;
        private Method method;

        public HandlerMethod(Object controller, Method method) {
            this.controller = controller;
            this.method = method;
        }

        public Object getController() {
            return controller;
        }

        public Method getMethod() {
            return method;
        }
    }

    @Override
    public void init() throws ServletException {
        super.init();
        // 必须初始化bean
        System.out.println("开始进行扫描包");
        try {
            // 初始化ApplicationContext
            ApplicationContext context = new ApplicationContext();
            // 先扫描service包，再扫描controller包，确保依赖的Bean先创建
            context.init("zdm");

            // 建立URL映射表
            initHandlerMapping();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化Handler映射表
     */
    private void initHandlerMapping() {
        System.out.println("开始建立URL映射表...");

        for (Object controller : BeanFactory.getAllBeans().values()) {
            if (controller.getClass().isAnnotationPresent(ZdmController.class)) {
                for (Method method : controller.getClass().getMethods()) {
                    if (method.isAnnotationPresent(ZdmRequestMapping.class)) {
                        ZdmRequestMapping mapping = method.getAnnotation(ZdmRequestMapping.class);
                        String url = mapping.value();

                        if (url != null && !url.isEmpty()) {
                            handlerMapping.put(url, new HandlerMethod(controller, method));
                            System.out.println("映射URL: " + url + " -> " + controller.getClass().getSimpleName() + "." + method.getName());
                        }
                    }
                }
            }
        }

        System.out.println("URL映射表建立完成，共映射 " + handlerMapping.size() + " 个接口");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String uri = req.getRequestURI();

        if (uri == null || uri.isEmpty()) {
            uri = "/";
        }

        resp.setContentType("text/html;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 直接从映射表中查找HandlerMethod
        HandlerMethod handlerMethod = handlerMapping.get(uri);

        if (handlerMethod != null) {
            try {
                // 获取方法参数
                Method method = handlerMethod.getMethod();
                Parameter[] parameters = method.getParameters();
                Object[] args = new Object[parameters.length];

                // 解析URL参数
                String queryString = req.getQueryString();
                Map<String, String> paramMap = new HashMap<>();
                if (queryString != null && !queryString.isEmpty()) {
                    String[] pairs = queryString.split("&");
                    for (String pair : pairs) {
                        String[] keyValue = pair.split("=");
                        if (keyValue.length == 2) {
                            paramMap.put(keyValue[0], keyValue[1]);
                        }
                    }
                }

                // 为方法参数赋值
                for (int i = 0; i < parameters.length; i++) {
                    Parameter parameter = parameters[i];
                    if (parameter.isAnnotationPresent(ZdmRequestParam.class)) {
                        ZdmRequestParam requestParam = parameter.getAnnotation(ZdmRequestParam.class);
                        String paramName = requestParam.value();
                        String paramValue = paramMap.get(paramName);
                        args[i] = paramValue;
                    } else {
                        args[i] = null;
                    }
                }

                // 调用方法
                String result = (String) method.invoke(handlerMethod.getController(), args);
                resp.getWriter().write(result);
            } catch (Exception e) {
                e.printStackTrace();
                resp.getWriter().write("执行方法时发生错误: " + e.getMessage());
            }
        } else {
            resp.getWriter().write("未找到路径404: " + uri);
        }
    }
}
